package com.allen.app.common.config.swagger.reader;

import com.allen.app.common.config.swagger.common.HideType;
import com.allen.app.common.config.swagger.common.ModelPropertyUtil;
import com.allen.app.common.utils.Maps;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import springfox.documentation.builders.ModelBuilder;
import springfox.documentation.schema.Model;
import springfox.documentation.schema.ModelProperty;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ApiListingBuilderPlugin;
import springfox.documentation.spi.service.contexts.ApiListingContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;


/**
 * 将ApiReadContext中ModelRef集合添加到documentation Models
 *
 * @author Leon (234239150@qq.com) created in 15:32 18.9.11
 */
@Slf4j
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public class ApiListingReader implements ApiListingBuilderPlugin {

    private ApiReaderContext context;

    public ApiListingReader(ApiReaderContext context) {
        this.context = context;
    }

    @Override
    public boolean supports(DocumentationType delimiter) {
        return true;
    }

    @Override
    public void apply(ApiListingContext apiListingContext) {
        context.getEnumAndHideParameter().forEach((name, resolvedType) -> {
            Model model = context.getModels().get(resolvedType.getErasedType().getSimpleName());
            if (Objects.nonNull(model)) {
                Map<String, ModelProperty> properties = new HashMap<>();
                model.getProperties().forEach((key, val) -> {
                    ModelProperty modelProperty = val;
                    Class<?> erasedType = val.getType().getErasedType();
                    if (erasedType.isEnum()) {
                        modelProperty = ModelPropertyUtil.enumModelProperty(val, erasedType);
                    }
                    if (context.getHideProperties().containsKey(name)) {
                        ApiReaderContext.ApiHideProperty item = context.getHideProperties().get(name);
                        if (item.getHideType().equals(HideType.HIDE)) {
                            if (item.modelFields().contains(key)) {
                                properties.put(key, modelProperty);
                            }
                        } else {
                            if (!item.modelFields().contains(key)) {
                                properties.put(key, modelProperty);
                            }
                        }
                    } else {
                        properties.put(key, modelProperty);
                    }
                });
                Model newModel = new ModelBuilder()
                        .id(model.getId())
                        .name(name)
                        .type(model.getType())
                        .qualifiedType(model.getQualifiedType())
                        .properties(properties)
                        .description(model.getDescription())
                        .baseModel(model.getBaseModel())
                        .discriminator(model.getDiscriminator())
                        .subTypes(model.getSubTypes())
                        .example(model.getExample())
                        .build();
                apiListingContext.apiListingBuilder().models(Maps.of(name, newModel));

            }
        });
    }


}
